#include <cstdio>
#include <fstream>
#include <cstring>

#include "types.h"
#include "functions.h"

using namespace std;

bool locateClickFile(const char *clickfile)
{
	printf(">>> locate click file '%s' :\n", clickfile);
	
	char c;
	bool bin;
	printf("saved as a binary file? (Y/n) ");
	c = GetChar();
	if (c == 'n' || c == 'N')
		bin = false;
	else bin = true;
	
	ifstream fin;
	ofstream fout;

	fin.open(clickfile, ios::in);
	if (!fin.is_open())	// input file open failure
	{
		OpenFileFailed(clickfile);
		return false;
	}
	
	char *locfile = NULL;
	if (bin)
	{
		formFilename(&locfile, clickfile, LOCBIN); // binary
		fout.open(locfile, ios::out | ios::binary);
	}
	else
	{
		formFilename(&locfile, clickfile, LOC);	// ASCII
		fout.open(locfile, ios::out);
	}
	if (!fout.is_open())	// output file open failure
	{
		OpenFileFailed(locfile);
		fin.close();
		return false;
	}
	
	int totalqueries = 0;
	bool first = true;
	int clickcount = 1;
	int location = 0;
	char curline[CLICKLINESIZE];
	char tmpID[IDLEN + 1];
	tmpID[IDLEN] = 0;
	uint64 curID = 0;
	uint64 preID = 0;

	char firstline[] = "QueryID\tLocation\tCount\n";
	fin.getline(curline, CLICKLINESIZE, '\n'); 
	if (!bin)	fout.write(firstline, strlen(firstline));	// reserved in ASCII file
	location = fin.tellg();	// first click position of the first query
	
	while (!fin.eof())
	{
		fin.getline(curline, CLICKLINESIZE, '\n');
		if (fin.gcount() == 0)	// the end of file is reached 
		{
			// output information about the last query
			if (bin)
			{
				ClickLocation tmp;
				tmp.ID = preID;
				tmp.location = location;
				tmp.count = clickcount;
				fout.write((char *)(&tmp), LOCSIZE);
			}
			else
			{
				uint642hexstr(preID, tmpID);
				fout << tmpID << '\t'
					<< location << '\t'
					<< clickcount << endl;
			}
			totalqueries++;
			printf(">>> locate %d queries\n", totalqueries);
			break;
		}
		
		// parse information needed
		strncpy(tmpID, curline, IDLEN);
		tmpID[IDLEN] = 0;
		hexstr2uint64(tmpID, &curID);
		if (preID == curID)
			clickcount++;
		else	// a new query
		{
			if (first)	// detect the first query
			{
				first = false;
				preID = curID;
				clickcount = 1;
			}
			else	// second query and the backward queries
			{
				// output information about the previous query
				if (bin)
				{
					ClickLocation tmp;
					tmp.ID = preID;
					tmp.location = location;
					tmp.count = clickcount;
					fout.write((char *)(&tmp), LOCSIZE);
				}
				else
				{
					uint642hexstr(preID, tmpID);
					fout << tmpID << '\t'
						<< location << '\t'
						<< clickcount <<endl;
				}
				totalqueries++;
				preID = curID;
				clickcount = 1;	// set back to 1
				// get the first click position of the new current query
				location = fin.tellg();
				location -= fin.gcount();
			}
		}
		
		if (totalqueries != 0 && totalqueries % PROGRESS == 0)
			printf("query %d\n", totalqueries);
	}
	
	fin.close();
	fout.flush();	// write the unwritten characters in the buffer to file(assume no error here)
	fout.close();
	printf(">>> locate OK: file '%s' ==> file '%s'\n", clickfile, locfile);
	delete [] locfile;
	return true;
}

void locateClicks()
{
	char *clickfiles[]={
		"srfp20060501-20060531.clicks.adult.txt",
		"srfp20060501-20060531.clicks.txt",
	};
	
	char c, b;
	printf("locate file:\n");
	printf("1: %s\n", clickfiles[0]);
	printf("2: %s\n", clickfiles[1]);
	printf("3: both 1 and 2\n");
	printf("0: exit\n");
	printf("choice: ");
	c = GetChar();
	switch (c)
	{
		case '3':
		case '1':	if (!locateClickFile(clickfiles[0]))
						printf(">>> ERROR: file '%s' failed\n", clickfiles[0]);
					if (c == '1') break;
					else
					{
						printf("Continue...(Y/n)? ");
						b = GetChar();
						if (b == 'n' || b == 'N')	break;
					}
		case '2':	if (!locateClickFile(clickfiles[1]))
						printf(">>> ERROR: file '%s' failed\n", clickfiles[1]);
		case '0':	break;
	}
}
